"use strict";
/** @format */
exports.__esModule = true;
// https://promisesaplus.com/
// promise三种状态 pending，fulfilled，rejected
var PromiseState;
(function (PromiseState) {
    PromiseState["PENDING"] = "pending";
    PromiseState["FULFILLED"] = "fulfilled";
    PromiseState["REJECTED"] = "rejected";
})(PromiseState || (PromiseState = {}));
/**
 * promise 处理程序是一个表现形式为 [[Resolve]](promise, x) 的抽象处理操作。
 * 如果 x 是 thenable 类型，它会尝试生成一个 promise 处理 x
 *
 * @template T
 * @param {MyPromise<T>} promise
 * @param {*} x
 * @param {PromiseResolve<T>} resolve
 * @param {(PromiseReject<T | any>)} reject
 * @returns
 */
var resolvePromise = function (promise, x, resolve, reject) {
    // 2.3.1 如果返回的promise 和 x 是指向同一个引用（循环引用），则抛出错误
    if (promise === x) {
        return reject(new TypeError('Chaining cycle detected for promise'));
    }
    // 如果 x 是一个 promise 实例，则采用它的状态
    if (x instanceof MyPromise) {
        // 2.3.2.1 如果 x 是 pending 状态，那么保留它（递归执行这个 promise 处理程序），直到 pending 状态转为 fulfilled 或 rejected 状态.
        if (x.currentState === PromiseState.PENDING) {
            x.then(function (value) {
                resolvePromise(promise, value, resolve, reject);
            }, reject);
        }
        else {
            x.then(resolve, reject);
        }
        return;
    }
    // 2.3.3 如果 x 是个对象或函数类型
    if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
        // 2.3.3.3.3 如果 resolvePromise 和 rejectPromise 已经被调用或以相同的参数多次调用的话吗，优先第一次的调用，并且之后的调用全部被忽略（避免多次调用）
        var hasCalled_1 = false;
        try {
            // 2.3.3.1 把 x.then 赋值给 then 变量
            var then = x.then;
            // 2.3.3.3 如果 then 是函数类型，那个用 x 调用它（将 then 的 this 指向 x）,第一个参数传 resolvePromise ，第二个参数传 rejectPromise：
            if (typeof then === 'function') {
                then.call(x, 
                // 2.3.3.3.1 如果或当 resolvePromise 被调用并接受一个参数 y 时，执行 [[Resolve]](promise, y)
                function (y) {
                    if (hasCalled_1)
                        return;
                    hasCalled_1 = true;
                    resolvePromise(promise, y, resolve, reject);
                }, 
                // 2.3.3.3.2 如果或当 rejectPromise 被调用并接受一个参数 r 时，执行 reject(r)
                function (r) {
                    if (hasCalled_1)
                        return;
                    hasCalled_1 = true;
                    reject(r);
                });
            }
            else {
                resolve(x);
            }
            // 2.3.3.2 如果捕获到 x.then 抛出的错误的话，需要 reject 这个promise
        }
        catch (error) {
            // 2.3.3.3.4.1 如果 resolvePromise 或 rejectPromise 已经被调用，那么忽略异常
            if (hasCalled_1)
                return;
            hasCalled_1 = true;
            // 2.3.3.3.4.2 否则，reject 这个异常
            reject(error);
        }
    }
    else {
        // 2.3.3.4 如果 then 不是函数类型，直接 resolve x（resolve(x)）
        resolve(x);
    }
};
var MyPromise = /** @class */ (function () {
    // 传入函数，接收两个方法改变状态
    function MyPromise(fn) {
        var _this = this;
        // promise 状态
        this.currentState = PromiseState.PENDING;
        // 成功回调队列
        this.resolvedCallbacks = [];
        // 失败回调队列
        this.rejectedCallbacks = [];
        this.resolve = function (value) {
            if (value instanceof MyPromise) {
                return value.then(_this.resolve, _this.reject);
            }
            setTimeout(function () {
                if (_this.currentState === PromiseState.PENDING) {
                    _this.currentState = PromiseState.FULFILLED;
                    _this.value = value;
                    _this.resolvedCallbacks.forEach(function (cb) { return cb(); });
                }
            });
        };
        this.reject = function (reason) {
            setTimeout(function () {
                if (_this.currentState === PromiseState.PENDING) {
                    _this.currentState = PromiseState.REJECTED;
                    _this.value = reason;
                    _this.rejectedCallbacks.forEach(function (cb) { return cb(); });
                }
            });
        };
        /**
         *一个 promise 必须提供一个 then 方法，用来获取当前或最终的 value 或 reason
         * 2.2.7 then 方法一定返回一个 promise
         * @param {PromiseResolve<T>} [onFulfilled]
         * @param {PromiseReject<T>} [onRejected]
         * @returns {MyPromise<T>}
         */
        this.then = function (onFulfilled, onRejected) {
            var promise;
            // 2.2.1.1 如果 onFulfilled 不是函数，它会被忽略
            var _onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : function (value) { return value; };
            // 2.2.1.2 如果 onRejected 不是函数，它会被忽略
            var _onRejected = typeof onRejected === 'function'
                ? onRejected
                : function (reason) {
                    throw reason;
                };
            // 2.2.6 promise 的 then 可以链式调用多次
            if (_this.currentState === PromiseState.PENDING) {
                promise = new MyPromise(function (resolve, reject) {
                    // 2.2.6.1 如果或当 promise 转态是 fulfilled 时，所有的 onFulfilled 回调回以他们注册时的顺序依次执行
                    _this.resolvedCallbacks.push(function () {
                        try {
                            var x = _onFulfilled(_this.value);
                            resolvePromise(promise, x, resolve, reject);
                        }
                        catch (r) {
                            reject(r);
                        }
                    });
                    // 2.2.6.2 如果或当 promise 转态是 rejected 时，所有的 onRejected 回调回以他们注册时的顺序依次执行
                    _this.rejectedCallbacks.push(function () {
                        try {
                            var x = _onRejected(_this.value);
                            resolvePromise(promise, x, resolve, reject);
                        }
                        catch (r) {
                            reject(r);
                        }
                    });
                });
                return promise;
            }
            // 2.2.2 如果 onFulfilled 是一个函数：
            // 2.2.2.1 它一定是在 promise 是 fulfilled 状态后调用，并且接受一个参数 value
            if (_this.currentState === PromiseState.FULFILLED) {
                promise = new MyPromise(function (resolve, reject) {
                    // 2.2.5 onFulfilled 和 onRejected 会作为函数形式调用 (也就是说，默认 this 指向 global，严格模式 undefined) [3.2]
                    setTimeout(function () {
                        try {
                            var x = _onFulfilled(_this.value);
                            resolvePromise(promise, x, resolve, reject);
                        }
                        catch (reason) {
                            reject(reason);
                        }
                    });
                });
                return promise;
            }
            // rejected状态
            if (_this.currentState === PromiseState.REJECTED) {
                promise = new MyPromise(function (resolve, reject) {
                    // 2.2.5 onFulfilled 和 onRejected 会作为函数形式调用 (也就是说，默认 this 指向 global，严格模式 undefined) [3.2]
                    setTimeout(function () {
                        try {
                            var x = _onRejected(_this.value);
                            resolvePromise(promise, x, resolve, reject);
                        }
                        catch (reason) {
                            reject(reason);
                        }
                    });
                });
                return promise;
            }
        };
        // Promise.prototype.catch 用于指定出错时的回调，是特殊的then方法，catch之后，可以继续 .then
        this["catch"] = function (onRejected) {
            return _this.then(null, onRejected);
        };
        // 不管成功还是失败，都会走到finally中,并且finally之后，还可以继续then。并且会将值原封不动的传递给后面的then.
        this["finally"] = function (onFinally) {
            return _this.then(function (value) { return MyPromise.resolve(onFinally()).then(function () { return value; }); }, function (reason) {
                return MyPromise.resolve(onFinally()).then(function () {
                    throw reason;
                });
            });
        };
        try {
            fn(this.resolve, this.reject);
        }
        catch (e) {
            this.reject(e);
        }
    }
    /**
     * Promise.all 接收一个promise数组,
     * 只有数组中全部的 Promise 都变为 resolve 的时候返回一个新的 Promise 实例，
     * 只要有一个失败，状态就变成 rejected
     *
     * @param {MyPromise<any>[]} iterable
     * @returns
     */
    MyPromise.all = function (iterable) {
        return new MyPromise(function (resolve, reject) {
            var result = [];
            iterable.forEach(function (promiseInstance, index) {
                promiseInstance.then(function (value) {
                    result[index] = value;
                    if (result.length === iterable.length) {
                        resolve(result);
                    }
                }, reject);
            });
        });
    };
    /**
     *  Promise.race(iterable)，接收一个promise数组
     * 当iterable参数里的任意一个子promise被成功或失败后，、父promise马上也会用子promise的成功返回值或失败
     *
     * @param {MyPromise<any>[]} iterable
     * @returns
     */
    MyPromise.race = function (iterable) {
        return new MyPromise(function (resolve, reject) {
            iterable.forEach(function (promiseInstance) {
                promiseInstance.then(function (value) { return resolve(value); }, reject);
            });
        });
    };
    MyPromise.resolve = function (value) {
        var promise = new MyPromise(function (resolve, reject) {
            resolvePromise(promise, value, resolve, reject);
        });
        return promise;
    };
    MyPromise.reject = function (value) {
        return new MyPromise(function (_resolve, reject) {
            reject(value);
        });
    };
    // promiseA+ 测试用
    MyPromise.deferred = function () {
        var result = {};
        result.promise = new MyPromise(function (resolve, reject) {
            result.resolve = resolve;
            result.reject = reject;
        });
        return result;
    };
    return MyPromise;
}());
exports["default"] = MyPromise;
